package utils

import (
	"code.alibaba-inc.com/agit/quarantine-helper/config"
	"context"
	"io"
	"os"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func TestGetCommitIDArray(t *testing.T) {
	var (
		assert = assert.New(t)
	)

	type testCase struct {
		reader io.Reader
		output []string
	}

	readerStrings := []string{"",
		"ca67efd8155f20f99b285b7a6951d9275845f5bd",
		"4869efa1d631d866d9ca04213c7082acd83c7fdf\nba744e29959ce0988da69c709284c892dc5c1be2"}

	testCases := []testCase{
		testCase{
			reader: strings.NewReader(readerStrings[0]),
			output: nil,
		},
		testCase{
			reader: strings.NewReader(readerStrings[1]),
			output: []string{"ca67efd8155f20f99b285b7a6951d9275845f5bd"},
		},
		testCase{
			reader: strings.NewReader(readerStrings[2]),
			output: []string{"4869efa1d631d866d9ca04213c7082acd83c7fdf", "ba744e29959ce0988da69c709284c892dc5c1be2"},
		},
	}
	for _, testCase := range testCases {
		idArray, err := GetCommitIDArray(testCase.reader)
		assert.Nil(err)
		assert.Equal(testCase.output, idArray)
	}
}

//func TestGetCommitObjectByID(t *testing.T) {
//	var (
//		assert = assert.New(t)
//	)
//	repoPath := "/tmp/quarantine-helper.git"
//	err := os.Mkdir(repoPath, os.ModePerm)
//	if err != nil {
//		panic(err)
//	}
//	defer func(dir string) {
//		os.RemoveAll(dir)
//	}(repoPath)
//	cmdArgs := []string{
//		"git",
//		"clone",
//		"--bare",
//		"http://gitlab.alibaba-inc.com/agit/quarantine-helper.git",
//		repoPath,
//	}
//	cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
//	err = cmd.Run()
//	assert.Nil(err)
//	repo, err := git.OpenRepository(repoPath)
//	assert.Nil(err)
//	assert.NotNil(repo)
//
//	commit, err := GetCommitObjectByID("ba744e29959ce0988da69c709284c892dc5c1be2", repo)
//	assert.Nil(err)
//	assert.Equal(commit.Id().String(), "ba744e29959ce0988da69c709284c892dc5c1be2")
//
//	commit, err = GetCommitObjectByID("", repo)
//	assert.NotNil(err)
//	assert.Nil(commit)
//
//	commit, err = GetCommitObjectByID("ba744e29959ce0988da69c709284c892dc5c1be3", repo)
//	assert.NotNil(err)
//	assert.Nil(commit)
//}

func TestGetCommitByID(t *testing.T) {
	type args struct {
		commitID string
	}
	tests := []struct {
		name    string
		args    args
		want    *GitCommit
		wantErr error
	}{
		{
			name: "get commit id",
			args: args{
				commitID: "f1621b474b056b42d2d5f7e2f36e908945a9dd0f",
			},
			want: &GitCommit{
				Id:      "f11600a3091860120539f6bb046a3fdced7c200f",
				Subject: []byte("Add B.log"),
				Body:    []byte("Add B.log\n"),
				Author: &CommitAuthor{
					Name:  []byte("A U Thor"),
					Email: []byte("author@example.com"),
					Date: func() time.Time {
						t, _ := time.Parse(time.RFC3339, "2005-04-07T15:15:13-07:00")
						return t
					}(),
					Timezone: nil,
				},
				Committer: &CommitAuthor{
					Name:  []byte("C O Mitter"),
					Email: []byte("committer@example.com"),
					Date: func() time.Time {
						t, _ := time.Parse(time.RFC3339, "2005-04-07T15:15:13-07:00")
						return t
					}(),
					Timezone: nil,
				},
				ParentIds: []string{"f1621b474b056b42d2d5f7e2f36e908945a9dd0f"},
			},
			wantErr: nil,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			os.Setenv(config.GitRepositoryPath, TestRepoPath)
			got, err := GetCommitByID(tt.args.commitID)
			if tt.wantErr != nil {
				assert.Equal(t, tt.wantErr, err)
				return
			}

			assert.Equalf(t, tt.want, got, "GetCommitByID(%v)", tt.args.commitID)
		})
	}
}

func TestGetLogData(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	type args struct {
		ctx      context.Context
		revision string
		format   string
	}
	tests := []struct {
		name    string
		args    args
		want    []string
		wantErr error
	}{
		{
			name: "get parent",
			args: args{
				ctx:      ctx,
				revision: "f1621b474b056b42d2d5f7e2f36e908945a9dd0f",
				format:   "%P",
			},
			want:    []string{"d1bc0607bd533e5184f943e74c0a8593dd0512d3"},
			wantErr: nil,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			os.Setenv(config.GitRepositoryPath, TestRepoPath)
			got, err := GetLogData(tt.args.ctx, tt.args.revision, tt.args.format)
			if tt.wantErr != nil {
				assert.Equal(t, tt.wantErr, err)
				return
			}

			assert.Equalf(t, tt.want, got, "GetLogData(%v, %v, %v)", tt.args.ctx, tt.args.revision, tt.args.format)
		})
	}
}
